--[[
 -- *名称:ThreeTakePairTypeAnalyzer
 -- *描述:[XXXXXXXXX]
 -- *版权:Copyright © 2016-2018 深圳市三只小熊科技有限公司 版权所有
 -- *作者:Administrator
 -- *创建日期:2017-11-09
 -- *修改日期:2017-11-09
 ]]
local DdzSuitAnalyzer = require(basePath.."suit/ddzsuitanalyzer");
local ThreeTakePairTypeAnalyzer = pokercore.class(DdzSuitAnalyzer,false);
local FourTakePairTypeAnalyzer = require(basePath.."suit/fourtakepair/fourtakepairtypeanalyzer");  --四带二
local ThreeTypeAnalyzer = require(basePath.."suit/three/threetypeanalyzer"); --三条
local Cards = require(basePath .. "domain/cards");
local fourTakePairTypeAnalyzer = pokercore.new(FourTakePairTypeAnalyzer) ;

ThreeTakePairTypeAnalyzer.TUPLE_SIZE = 5 ;

local TUPLE_SIZE = 5 ;
--@Override
function ThreeTakePairTypeAnalyzer:getSuitType()
	return DdzCardTypes.THREE_TAKE_PAIR;
end

--@Override
function ThreeTakePairTypeAnalyzer:doCheckRule(cards,term,result)
	if (result:getCardNum() == ThreeTakePairTypeAnalyzer.TUPLE_SIZE) then -- // 五张牌
			if (result:getNoneLaziValueCounter():hasJoker()) then -- // 三带一对不能出现王
				return false;
			else 
				local allValues = result:getNoneLaziValueCounter():getAllValues();
				if (#allValues > 2) then -- // 有三种点数
					return false;
				else  --// 没有，有一种或两种点数
					if (result:getLaziCardNum() == 0) then--// 没有癞子
						return #(result:getNoneLaziValueCounter():getValuesInCount(3)) > 0 
								and #(result:getNoneLaziValueCounter():getValuesInCount(2)) > 0;
					elseif (result:getLaziCardNum() == 1) then -- // 1张癞子// 3334* 3344* 3333*
						return #(result:getNoneLaziValueCounter():getValuesInCount(4)) == 0; --// 排除3333* 情况
					elseif (result:getLaziCardNum() == 2) then -- // 2张癞子 344** 333**
						return true;
					elseif (result:getLaziCardNum() == 3) then -- // 3张癞子 34*** 33***
						return true;
					elseif (result:getLaziCardNum() == 4) then -- // 4张癞子 3**** 歧义牌型默认炸弹
						return true;
					else -- // 全是癞子，默认炸弹
						return false;
					end
				end
			end
	else 
		return false;
	end
end


--@Override
function ThreeTakePairTypeAnalyzer:doAnalysizeLaizi(cards,term,onlyMaxValue)
	local cardsResult = {}
	local result = cards:getResult();
    local laiziCardNum = result:getLaziCardNum();
	if (laiziCardNum == 4) then -- // 4张癞子 3**** 
		self:makeItInAllValues(cards, term, onlyMaxValue, cardsResult);
	elseif (laiziCardNum == 3) then -- // 三张癞子
		local count_2_values = result:getNoneLaziValueCounter():getValuesInCount(2);
		if (count_2_values.size() > 0) then -- // 33***
			self:makeItInAllValues(cards, term, onlyMaxValue, cardsResult);
		else --// 34***
			self:makeItInSomeValues(cards, term, onlyMaxValue, cardsResult);
		end
	else --// 没有癞子 一张癞子 两张癞子 3334* 3344* 344** 333**
		self:makeItInSomeValues(cards, term, onlyMaxValue, cardsResult);
	end
	return cardsResult;
end


--[[
 -- 在已知值中寻找三带一对
 -- @DateTime 2017-11-09
 -- @param    cards [description]
 -- @param    term [description]
 -- @param    onlyMaxValue [description]
 -- @param    cardsResult [description]
 -- @return    [description]
 ]]
function ThreeTakePairTypeAnalyzer:makeItInSomeValues(cards,term,onlyMaxValue,cardsResult)
	local result = cards:getResult();
	local laiziCardList = cards:subList(result:getCardNum() - result:getLaziCardNum()+1, result:getCardNum());
	local allValues = result:getNoneLaziValueCounter():getAllValues(); --// 非癞子的点数
	local laiziCardNum = result:getLaziCardNum();
	for i = #allValues , 1, -1 do
		local valueTemp = allValues[i];
		local valueTempNum = result:getNoneLaziValueCounter():getValueCount(valueTemp);
		local needLaiziNum = 3 - valueTempNum; --// 需要填补几个癞子
		if (laiziCardNum >= needLaiziNum) then -- // 可能癞子不够
			local laiziCardIndex = 0;
			for j = 1, needLaiziNum do
				laiziCardIndex = laiziCardIndex +1 ;
				laiziCardList[laiziCardIndex]:changeCard(valueTemp);
				
			end
			for j = 1, #allValues do
				local j_valueTemp = allValues[j];
				if (j_valueTemp ~= valueTemp) then -- // 落单牌补齐成对子
					local j_valueTempNum = result:getNoneLaziValueCounter():getValueCount(j_valueTemp);
					if (j_valueTempNum % 2 ~= 0) then
						laiziCardIndex = laiziCardIndex + 1;
						laiziCardList[laiziCardIndex]:changeCard(j_valueTemp);
					end
				end
			end
			for  j = laiziCardIndex + 1,laiziCardNum do
				laiziCardList[j].changeCard(laiziCardList[laiziCardIndex+1]:getNumber());
			end
			local cardsCopy = cards:clone();
			self:analysize(cardsCopy, term);
			table.insert(cardsResult,cardsCopy:clone());
			if (onlyMaxValue) then
				break; --// 取完最大一组就跳出
			end
		end
	end
end


---
 -- 遍历所有值寻找三带一对
 -- @DateTime 2017-11-09
 -- @param    cards [description]
 -- @param    term [description]
 -- @param    onlyMaxValue [description]
 -- @param    cardsResult [description]
 -- @return    [description]
 --
function ThreeTakePairTypeAnalyzer:makeItInAllValues(cards,term,onlyMaxValue,cardsResult)
	local result = cards:getResult();
	local laiziCardList = cards:subList(result:getCardNum() - result:getLaziCardNum()+1, result:getCardNum());
	local allValues = result:getNoneLaziValueCounter():getAllValues(); --// 非癞子的点数
	local laiziCardNum = result:getLaziCardNum();
	--print("#################e231r42314243frdsefdsfds")
	for  valueTemp = PokerGameConstant.NUMBER_2_VALUE, PokerGameConstant.NUMBER_3_VALUE,-1 do
		local valueTempNum = result:getNoneLaziValueCounter():getValueCount(valueTemp);
		local needLaiziNum = 3 - valueTempNum; --// 需要填补几个癞子
		local laiziCardIndex = 0;
		for i = 1, needLaiziNum do
			laiziCardIndex = laiziCardIndex + 1;
			laiziCardList[laiziCardIndex]:changeCard(valueTemp);
		end
		for  j = #allValues , 1, -1 do
			local j_valueTemp = allValues[j];
			if (j_valueTemp ~= valueTemp) then
				local j_valueTempNum = result:getNoneLaziValueCounter():getValueCount(j_valueTemp);
				if (j_valueTempNum % 2 ~= 0) then -- // 遇单补齐
					laiziCardIndex = laiziCardIndex + 1;
					laiziCardList[laiziCardIndex]:changeCard(j_valueTemp);
				end
			end
		end
		for j = laiziCardIndex+1, laiziCardNum do
			laiziCardList[j].changeCard(laiziCardList[laiziCardIndex+1]:getNumber());
		end
		local cardsCopy = cards:clone();
		self:analysize(cardsCopy, term);
		table.insert(cardsResult,cardsCopy:clone());
		if (onlyMaxValue) then
			break; --// 取完最大一组就跳出
		end
	end
end


--提牌算法

--@Override
function ThreeTakePairTypeAnalyzer:containsPossibleCards(handCards, term) 
	local result = handCards:getResult();
	return result:getCardNum() - result:getJokerCardNum() >= TUPLE_SIZE;
end
	
--/** 最多使用癞子的数量 */
local MAX_USE_LAIZI_CARD_NUM = 5;

--/** 防重复判定的比例值 参照 int key = count_3_value * TUPLE_WEIGHT + count_1_value; */
local TUPLE_WEIGHT = 1000000;

--/** 癞子权重，区分癞子变成的5 和 原本就是5 */
local LAIZI_WEIGHT = 1000;
	
--@Override
function ThreeTakePairTypeAnalyzer:doListPossibleCards(handCards,term) 
	local cardsResult = {} ;
	--// 非癞子部分
	local result = handCards:getResult();
	local noneLaiziCardList = handCards:subList(1, result:getNoneCardNum());
	local noneLaiziCards = DdzTypeUtil.createCardsCopy(noneLaiziCardList);
	noneLaiziCards:setResult(handCards:getResult():clone());
	local noneLaiziCardsResult = noneLaiziCards:getResult();
	noneLaiziCardsResult:collectNumber(noneLaiziCards, term);
	--// 癞子部分
	local laiziCardList = handCards:subList(result:getNoneCardNum()+1, result:getCardNum());
	local laiziCards = DdzTypeUtil.createCardsCopy(laiziCardList);
	laiziCards:setResult(handCards:getResult():clone());
	local laiziCardsResult = laiziCards:getResult();
	laiziCardsResult:collectNumber(laiziCards, term);
	
	local maxLoseValue = 0; --// 寻找最大遗失的牌 让***5可以出现，但是仅一次
	for valueTemp = PokerGameConstant.NUMBER_2_VALUE --// 从小开始
			,PokerGameConstant.NUMBER_3_VALUE, -1 do
		if (result:getNoneLaziValueCounter():getValueCount(valueTemp) == 0) then
			maxLoseValue = valueTemp;
			break;
		end
	end
	local laiziCardNum = result:getLaziCardNum();
	local maxUseLaiziCardNum = MAX_USE_LAIZI_CARD_NUM < laiziCardNum and MAX_USE_LAIZI_CARD_NUM or laiziCardNum;
	local exsitKeys = {}; -- // 记录已经组成三带一的value
	for useLaiziCardNum = 0,maxUseLaiziCardNum do
		if (useLaiziCardNum < MAX_USE_LAIZI_CARD_NUM) then --// 用了 0.1.2.3 个癞子
			for valueTemp = PokerGameConstant.NUMBER_3_VALUE  --// 从小开始
					,PokerGameConstant.NUMBER_2_VALUE do
				local modelCardsCopy = noneLaiziCards:clone(); -- // 常规牌副本
				local modelResultCopy =  modelCardsCopy:getResult();
				local useLaiziCardList = DdzTypeUtil.cloneSublistedCards(laiziCards, 1, useLaiziCardNum); --// 补癞子
				local valueTempNum = modelResultCopy:getNoneLaziValueCounter():getValueCount(valueTemp);
				local needLaiziCardNum = ThreeTypeAnalyzer.TUPLE_SIZE - valueTempNum;
				needLaiziCardNum = needLaiziCardNum > 0 and needLaiziCardNum or 0;
				if (needLaiziCardNum == 0) then
					local removedCardList = DdzTypeUtil.cloneRemovedCards(modelCardsCopy, valueTemp, ThreeTypeAnalyzer.TUPLE_SIZE);
					local tupleCards = pokercore.new(Cards,removedCardList);
					local remainCards = DdzTypeUtil.cloneCardsAndAddCardList(modelCardsCopy, useLaiziCardList);
					local takenCardsList = fourTakePairTypeAnalyzer:repeatSelectPairCards(remainCards, 1, term);
					for _,takenCards in ipairs(takenCardsList) do
						local resultCards = DdzTypeUtil.cloneCardsAndAddCards(tupleCards, takenCards);
						local key = valueTemp * TUPLE_WEIGHT;
						for _,card in ipairs(takenCards.cardList) do
							key = key + card:getValue();
							if card:isLazi() then -- // 癞子权重，区分癞子变成的5 和 原本就是5
								key = key + card:getValue() * LAIZI_WEIGHT;
							end
						end
						if not exsitKeys[key] and self:match(resultCards, term) then
							exsitKeys[key] = true;
							self:analysize(resultCards, term);
							table.insert(cardsResult,resultCards);
						end
					end
				else -- // 需要癞子来拼凑
					if (needLaiziCardNum == ThreeTypeAnalyzer.TUPLE_SIZE 
							and valueTemp ~= maxLoseValue) then
						--// 这里是对癞子做tuple的去重
						--// 否则会出现 ***带99 既能是 333带99 也能使 444带99 555带99
						--continue;			
					elseif (useLaiziCardNum >= needLaiziCardNum) then -- // 癞子足够拼凑
						----dump(modelCardsCopy,"modelCardsCopy--#####")
						----print("#######valueTempNum->",valueTempNum)
						----print("#######valueTemp->",valueTemp)
						local removedCardList = DdzTypeUtil.cloneRemovedCards(modelCardsCopy, valueTemp, valueTempNum);
						----dump(removedCardList,"removedCardList--#####")
						for i = 1, needLaiziCardNum  do
							local laiziCard =  table.remove(useLaiziCardList,1);
							laiziCard:changeCard(valueTemp);
							table.insert(removedCardList,laiziCard);
						end
						--// 赋值要成对
						local value = -1;
						for _,laiziCard in ipairs(useLaiziCardList) do
							if (value == -1) then
								value = laiziCard:getValue();
							end
							laiziCard:changeCard(value);
						end
						local tupleCards = pokercore.new(Cards,removedCardList);
						local remainCards = DdzTypeUtil.cloneCardsAndAddCardList(modelCardsCopy, useLaiziCardList);
						local takenCardsList = fourTakePairTypeAnalyzer:repeatSelectPairCards(remainCards, 1, term);
						----dump(tupleCards,"tupleCards--#####")
						----dump(takenCardsList,"takenCardsList--#####")
						for _,takenCards in ipairs (takenCardsList) do
							local resultCards = DdzTypeUtil.cloneCardsAndAddCards(tupleCards, takenCards);
							local key = valueTemp * TUPLE_WEIGHT;
							for _,card in ipairs(takenCards.cardList) do
								key = key + card:getValue();
								if card:isLazi() then -- // 癞子权重，区分癞子变成的5 和 原本就是5
									key = key + card:getValue() * LAIZI_WEIGHT;
								end
							end
							if not exsitKeys[key] and self:match(resultCards, term) then
								exsitKeys[key] = true;
								self:analysize(resultCards, term);
								table.insert(cardsResult,resultCards);
							end
						end
					end
				end
			end
		else -- // 用了 5个癞子
			-- for valueTemp = PokerGameConstant.NUMBER_3_VALUE --// 从小开始
			-- 		,  PokerGameConstant.NUMBER_2_VALUE do
			-- 	Cards modelCardsCopy = laiziCards.clone(); // 常规牌补上癞子
			-- 	DdzAnalysisResult modelResultCopy = (DdzAnalysisResult) modelCardsCopy.getResult();
			-- 	if (modelResultCopy.getAllValueCounter().getValueCount(valueTemp) >= ThreeTypeAnalyzer.TUPLE_SIZE) {
			-- 		List<Card> removedCardList = DdzTypeUtil.cloneRemovedCards(modelCardsCopy, valueTemp, ThreeTypeAnalyzer.TUPLE_SIZE);
			-- 		Cards tupleCards = new Cards(removedCardList);
			-- 		List<Cards> takenCardsList = fourTakePairTypeAnalyzer.repeatSelectPairCards(modelCardsCopy, 1, term);
			-- 		for (Cards takenCards : takenCardsList) {
			-- 			Cards resultCards = DdzTypeUtil.cloneCardsAndAddCards(tupleCards, takenCards);
			-- 			for (Card card : resultCards) {
			-- 				if (((DdzCard)card).hasNotChanged()) { // 有的经过处理已经被赋值了不能再改变
			-- 					((DdzCard)card).changeCard(card.getValue());
			-- 				}
			-- 			}
			-- 			if (match(resultCards, term)) {
			-- 				analysize(resultCards, term);
			-- 				cardsResult.add(resultCards);
			-- 			}
			-- 		}
			-- 	}
			-- }
			for valueTemp = PokerGameConstant.NUMBER_3_VALUE --// 从小开始
					, PokerGameConstant.NUMBER_2_VALUE do
				local modelCardsCopy = laiziCards:clone();  --// 常规牌补上癞子
				local modelResultCopy =  modelCardsCopy:getResult();
				if (modelResultCopy:getAllValueCounter():getValueCount(valueTemp) >= ThreeTypeAnalyzer.TUPLE_SIZE) then
					local removedCardList = DdzTypeUtil.cloneRemovedCards(modelCardsCopy, valueTemp, ThreeTypeAnalyzer.TUPLE_SIZE);
					local tupleCards = pokercore.new(Cards,removedCardList);
					local takenCardsList = fourTakePairTypeAnalyzer:repeatSelectPairCards(modelCardsCopy, 1, term);
					for _,takenCards in ipairs(takenCardsList) do
						local resultCards = DdzTypeUtil.cloneCardsAndAddCards(tupleCards, takenCards);
						for _,card in ipairs(resultCards) do
							if card:hasNotChanged() then -- // 有的经过处理已经被赋值了不能再改变
								card:changeCard(card:getValue());
							end
						end
						if (self:match(resultCards, term)) then
							--// 保证排序
							self:analysize(resultCards, term);
							table.insert(cardsResult,resultCards);
						end
					end
				end
			end
		end
	end
	return cardsResult;
end





return ThreeTakePairTypeAnalyzer;

